﻿using LogSystem;
using Pathfinding;
using System;
using UnityEngine;
using XLua;

namespace Yoozoo.Core.PathFinder
{
    public class GgameGridGraph : MonoBehaviour
    {
        public bool buildOnAwake;
        
        // 寻路网格左下角对应的城市格子坐标
        [SerializeField]
        private Vector2Int _GraphLetBottomCityGrid = Vector2Int.zero;
        // 寻路网格右上角对应的城市格子坐标
        [SerializeField]
        private Vector2Int _GraphRightTopCityGrid = Vector2Int.zero;
        
        private GridGraph _gridGraph;
        public Action OnGridGraphPostScan;

        private Vector2 _randomMapPenaltyOffset = new Vector2(2, 2);
        
        private void Awake()
        {
            AstarPath.OnGraphPostScan += OnGraphPostScan;
            if (buildOnAwake)
            {
                Build();
            }
        }

        private void Update()
        {
            // if (Input.GetKeyDown(KeyCode.Q))
            // {
            //     CloseArea(new Vector2Int(0,0),new Vector2Int(32,32));
            // }
            //
            // if (Input.GetKeyDown(KeyCode.W))
            // {
            //     OpenArea(new Vector2Int(0,0),new Vector2Int(32,32));
            // }
            //
            // if (Input.GetKeyDown(KeyCode.E))
            // {
            //     Refresh();
            // }
        }
        
        public Vector2Int ConvertCityGridToGraphGrid(Vector2 cityGrid)
        {
            return ConvertCityGridToGraphGrid((int)cityGrid.x, (int)cityGrid.y);
        }

        public Vector2Int ConvertCityGridToGraphGrid(int cityGridX, int cityGridY)
        {
            if (cityGridX < _GraphLetBottomCityGrid.x || cityGridY < _GraphLetBottomCityGrid.y || cityGridX > _GraphRightTopCityGrid.x || cityGridY > _GraphRightTopCityGrid.y)
            {
                // Debug.LogErrorFormat(LogModule.City,"ConvertCityGridToGraphGrid 超出范围 cityGrid.x = {0} _GraphLetBottomCityGrid.x={1}  cityGrid.y = {2}  _GraphLetBottomCityGrid.y ={3}",cityGrid.x,_GraphLetBottomCityGrid.x,cityGrid.y,_GraphLetBottomCityGrid.y);
                return Vector2Int.zero;
            }
            return new Vector2Int(cityGridX - _GraphLetBottomCityGrid.x, cityGridY - _GraphLetBottomCityGrid.y);
        }

        public void Build(Action callback = null)
        {
            AstarData data = AstarPath.active.data;
            var graphs = data.graphs;
            for (int i = 0; i < graphs.Length; i++)
            {
                if (graphs[i] == null) continue;

                if (graphs[i].name == "RandomMap")
                {
                    _gridGraph = graphs[i] as GridGraph;
                }
            }
            // GridGraph gg = data.AddGraph(typeof(GridGraph)) as GridGraph;
            // _gridGraph = gg;
            //
            // int width = 80;
            // int depth = 80;
            // float nodeSize = 2.5f;
            //
            // gg.name = "RandomMap";
            // gg.center = new Vector3(0, 0, 0);
            // gg.rotation = new Vector3(0, 45, 0);
            //
            // gg.SetDimensions(width, depth, nodeSize);
            //
            //
            // gg.neighbours = NumNeighbours.Four;
            //
            // gg.collision = new GraphCollision();
            // gg.collision.collisionCheck = false;
            // gg.collision.heightCheck = false;
            // gg.collision.mask = 0;
            if (callback!=null)
            {
                OnGridGraphPostScan += callback;
            }
            AstarPath.active.Scan(_gridGraph);
        }
        
        public void CloseArea(Vector2 lb,Vector2 tp,Action callback = null)
        {
            if (tp.x < lb.x || tp.y < lb.y)
            {
                Debug.LogWarningFormat(LogModule.City,"CloseArea 范围错误 tp.x = {0} lb.x={1}  tp.y = {2}  lb.y ={3}",tp.x,lb.x,tp.y,lb.y);
                callback?.Invoke();
                return;
            }

            lb = ConvertCityGridToGraphGrid(lb);
            tp = ConvertCityGridToGraphGrid(tp);

            var expandlb = new Vector2(Mathf.Max((lb.x - _randomMapPenaltyOffset.x), 1), Mathf.Max((lb.y - _randomMapPenaltyOffset.y), 1));
            var expandtp = new Vector2(Mathf.Min((tp.x + _randomMapPenaltyOffset.x), _gridGraph.width), Mathf.Min((tp.y + _randomMapPenaltyOffset.y), _gridGraph.depth));
            for (int i = (int)expandlb.x; i < expandtp.x; i++)
            {
                for (int j = (int)expandlb.y; j < expandtp.y; j++)
                {
                    if (i >= lb.x && j >= tp.y && i <= tp.x && j <= tp.y) // 跳过房子占领格子
                    {
                        continue;
                    }
                    var node = _gridGraph.GetNode(i,j);
                    if (node == null)
                    {
                        //UnityEngine.Debug.LogError($"获取节点错误：{i},{j}");
                        continue;
                    }

                    node.Penalty = 3000; // 增加房子周围权重，让npc尽量不挨着房子走路。
                }
            }
            
            
            AstarPath.active.AddWorkItem(new AstarWorkItem(ctx =>
            {
                if (_gridGraph == null)
                {
                    callback?.Invoke();
                    return;
                }
                for (int i = (int)lb.x; i < tp.x; i++)
                {
                    for (int j = (int)lb.y; j < tp.y; j++)
                    {
                        var node = _gridGraph.GetNode(i,j);
                        if (node == null)
                        {
                            //UnityEngine.Debug.LogError($"获取节点错误：{i},{j}");
                            continue;
                        }
                        node.Walkable = false;
                        _gridGraph.CalculateConnectionsForCellAndNeighbours(i, j);
                    }
                }
                
                callback?.Invoke();
            }));
        }

        //根据传过来的格子列表，直接设置
        public void UpdateAreaByGridList(LuaTable needRefreshList)
        {
            AstarPath.active.AddWorkItem(new AstarWorkItem(ctx =>
            {
                for (int i = 1; i <= needRefreshList.Length; i++)
                {
                    var item = needRefreshList.Get<int,LuaTable>(i);
                    int x = item.Get<string,int>("x");
                    int y = item.Get<string,int>("y");
                    Vector2Int graphGrid = ConvertCityGridToGraphGrid(x, y);
                    x = graphGrid.x;
                    y = graphGrid.y;
                    int canWalk = item.Get<string,int>("canWalk");
                    var node = _gridGraph.GetNode(x,y);
                    if (node == null)
                    {
                        continue;
                    }
                    node.Walkable = canWalk == 0;
                    _gridGraph.CalculateConnectionsForCellAndNeighbours(x, y);
                }
            }));
        }

        public void OpenArea(Vector2 lb,Vector2 tp,Action callback = null)
        {
            if (tp.x < lb.x || tp.y < lb.y)
            {
                Debug.LogError(LogModule.City,"OpenArea 范围错误");
                callback?.Invoke();
                return;
            }
            
            lb = ConvertCityGridToGraphGrid(lb);
            tp = ConvertCityGridToGraphGrid(tp);

            var expandlb = new Vector2(Mathf.Max((lb.x - _randomMapPenaltyOffset.x), 1), Mathf.Max((lb.y - _randomMapPenaltyOffset.y), 1));
            var expandtp = new Vector2(Mathf.Min((tp.x + _randomMapPenaltyOffset.x), _gridGraph.width), Mathf.Min((tp.y + _randomMapPenaltyOffset.y), _gridGraph.depth));
            for (int i = (int)expandlb.x; i < expandtp.x; i++)
            {
                for (int j = (int)expandlb.y; j < expandtp.y; j++)
                {
                    if (i >= lb.x && j >= tp.y && i <= tp.x && j <= tp.y) // 跳过房子占领格子
                    {
                        continue;
                    }
                    var node = _gridGraph.GetNode(i,j);
                    if (node == null)
                    {
                        //UnityEngine.Debug.LogError($"获取节点错误：{i},{j}");
                        continue;
                    }

                    node.Penalty = 0;
                }
            }
            
            AstarPath.active.AddWorkItem(new AstarWorkItem(ctx =>
            {
                for (int i = (int)lb.x; i < tp.x; i++)
                {
                    for (int j = (int)lb.y; j < tp.y; j++)
                    {
                        var node = _gridGraph.GetNode(i,j);
                        if (node == null)
                        {
                            //UnityEngine.Debug.LogError($"获取节点错误：{i},{j}");
                            continue;
                        }
                        node.Walkable = true;
                        _gridGraph.CalculateConnectionsForCellAndNeighbours(i, j);
                    }
                }
                callback?.Invoke();
            }));
        }
        
        public void Refresh()
        {
            AstarPath.active.FlushWorkItems();
        }
        
        
        private void OnGraphPostScan(NavGraph graph)
        {
            if (graph == _gridGraph)
            {
                OnGridGraphPostScan?.Invoke();
            }
        }
    }
}
